package com.xymtop.sqlcater.core.sql.sqlparser.toobj.parse;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.xymtop.sqlcater.core.sql.sqlexecute.select.entity.*;
import com.xymtop.sqlcater.core.sql.sqlparser.toobj.entity.SqlExecTree;
import com.xymtop.sqlcater.core.sql.sqlparser.toobj.entity.SqlQueryNode;
import com.xymtop.sqlcater.core.sql.sqlparser.tosql.entity.sql.AppContent;
import com.xymtop.sqlcater.core.sql.sqlparser.tosql.utils.CaterFileUtil;
import lombok.Data;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

//解析器
@Data
public class Parser {


   private SelectAppContent selectAppContent;
   private SqlExecTree sqlExecTree;

   public static Parser Parser(Object obj){
       Parser parser = new Parser();

       if(obj instanceof  SelectAppContent){

           //从SelectAppContent转为SqlExecTree
           parser.setSelectAppContent((SelectAppContent) obj);


       }else if(obj instanceof  SqlExecTree) {

           parser.setSqlExecTree((SqlExecTree) obj);
       }else if(obj instanceof  AppContent){

       }

       return parser;
   }


   public Parser parse(){

       if(selectAppContent!=null){
           toTree();
       }else {
           toApp();
       }

       return this;
   }

    private void toApp() {

    }

    private void toTree(){
       //创建主树
        SqlExecTree tree = new SqlExecTree();

        tree.setName(selectAppContent.getName());



        List<SqlExecTree> treeSubNodes = new ArrayList<>();

        //循环遍历，构建子节点
        for(SqlSelect sqlSelect : selectAppContent.getSelects()){

            //构建子节点
            SqlExecTree subTree = buildSubNode(sqlSelect);


            //不是主节点
            if(!sqlSelect.getName().equals("run")){
                //添加子节点
                treeSubNodes.add(subTree);
            }else {
                tree = subTree;
            }

        }

        tree.setSqlExecTrees(treeSubNodes);
        this.sqlExecTree = tree;
   }

    private SqlExecTree buildSubNode(SqlSelect sqlSelect) {
       SqlExecTree subTree = new SqlExecTree();

       //先构建查询节点树
        SqlExecTree query = buildQuery(sqlSelect);

        //再构建join树
        SqlExecTree join = buildJoin(sqlSelect);

        //合并
        subTree = contact(query,join);

        subTree.setName(sqlSelect.getName());
        return subTree;
    }


    private SqlExecTree buildQuery(SqlSelect sqlSelect){

       SqlExecTree tree = new SqlExecTree();
       tree.setName("query");
       if(sqlSelect!=null){
           for(SelectCollect selectCollect : sqlSelect.getSelectCollects()){

               if(selectCollect.getSelectCollectType()== SelectCollectType.SQLQUERY){
                   //需要进一步查询

               }else {
                   SqlQueryNode sqlQueryNode = new SqlQueryNode();
                   sqlQueryNode.setName(sqlSelect.getName());
                   tree.setSqlQueryNode(sqlQueryNode);
                   tree.setIsParse(true);
                   tree.setIsMain(false);
               }
           }
       }

       return tree;

    }


    private SqlExecTree buildJoin(SqlSelect sqlSelect){

        SqlExecTree tree = new SqlExecTree();
        tree.setName("join");
        if(sqlSelect!=null) {


            for (SqlJoin sqlJoin : sqlSelect.getSqlJoins()) {

                SelectCollect selectCollect = sqlJoin.getSelectCollect2();

                if (selectCollect.getSelectCollectType() == SelectCollectType.SQLQUERY) {
                    //需要进一步查询

                } else {
                    SqlQueryNode sqlQueryNode = new SqlQueryNode();
                    sqlQueryNode.setName(sqlSelect.getName());
                    tree.setSqlQueryNode(sqlQueryNode);
                    tree.setIsParse(true);
                    tree.setIsMain(false);
                }
            }
        }

        return tree;
    }

    //合并树
    private SqlExecTree contact(SqlExecTree queryTree,SqlExecTree joinTree){
        SqlExecTree tree = new SqlExecTree();
        List<SqlExecTree> trees = new ArrayList<>();
        trees.add(queryTree);
        trees.add(joinTree);
        tree.setSqlExecTrees(trees);
        return tree;
    }

    public  void  out(String path) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        CaterFileUtil.write(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(this.getSqlExecTree()),path);
    }

}
